
#include <iostream>
#include <thread>
#include <future>
#include <vector>
#include <algorithm>
// #include <latch>
using namespace std;

#include "ScheduledThreadPool.hpp"
void func(int a)
{
    cout << "func : " << a << endl;
}
int main()
{
    tulun::ScheduledThreadPool mypool(10, 1);

    mypool.execute(3, func, 3);
    mypool.execute(5, func, 5);
    mypool.execute(1, func, 1);
    mypool.execute(8, func, 8);

    std::this_thread::sleep_for(std::chrono::seconds(2));

    cout << "main end..." << endl;
    return 0;
}

#if 0
#include "Timer.hpp"
#include "TimerManage.hpp"

void funa()
{
    static int x = 0;
    cout << "funa: x : " << x++ << endl;
}
void funb()
{
    static int x = 0;
    cout << "funb: x : " << x++ << endl;
}
void func()
{
    static int x = 0;
    cout << "func: x : " << x++ << endl;
}
int main()
{
    tulun::TimerMap timermap;
    tulun::Timer tv1, tv2, tv3;
    tv1.init();
    tv2.init();
    tv3.init();
    timermap.init(-1);
    
    tv1.set_timer(funa, 5000);
    tv2.set_timer(funb, 3000);
    tv2.set_timer(func, 1000);
    timermap.add_timer(tv1);
    timermap.add_timer(tv2);
    timermap.add_timer(tv3);
    std::this_thread::sleep_for(std::chrono::seconds(100));
    return 0;
}

#include "SyncQueue_4.hpp"
#include "WorkStealingPool.hpp"
class my_latch
{
private:
    std::atomic_int count_;
    std::mutex mutex_;
    std::condition_variable cond_;

public:
    my_latch(int num = 1) : count_(num) {}
    ~my_latch() {}
    void count_down()
    {
        std::lock_guard<std::mutex> lock(mutex_);
        if (--count_ == 0)
        {
            cond_.notify_all();
        }
    }
    void wait()
    {
        std::unique_lock<std::mutex> lock(mutex_);
        while (count_ != 0)
        {
            cond_.wait(lock);
        }
    }
};

int Add(int a, int b, int s)
{
    clog << "Add begin ..." << endl;
    int c = a+b;
    clog << "Add end ..." << endl;
    return c;
}
void Add_a(int ch, int x, int y, tulun::WorkStealingPool &mypool)
{
    auto r = mypool.Submit(Add, x, y, rand() % 10);
    cout << "Add_" << ch << r.get() << endl;
}
int main()
{
    const int n = 2000;
    tulun::WorkStealingPool mypool;
    std::thread tha[n];
    int m = 0;
    for (int i = 0; i < n; ++i)
    {
        try
        {
            tha[i] = std::thread(Add_a, i, i + 20, i + 10, std::ref(mypool));
            m = i;
        }
        catch (std::system_error &e)
        {
            cout << e.what() << endl;
            break;
        }
    }
    for (int i = 0; i <= m; ++i)
    {
        tha[i].join();
    }
    cout << "thread num:" << m << endl;
    return 0;
}


static const int ksize = 1000000;
int n = 1000000;
int m = 1000;
my_latch lat(n);
std::atomic_int num = 0;
//std::vector<latch> veclat(n);
void RandValue(std::vector<std::deque<int>> &arver, int i, int m)
{
    srand(time(nullptr));
   // arver[i].reserve(m);
    for (int j = 0; j < m; ++j)
    {
        //arver[i].push_back(rand() % ksize);
        arver[i][j] = rand()%ksize;
    }
    //vecalt[i].count_down();
    lat.count_down();
}
void SortVer(std::vector<std::deque<int>> &arver, int i)
{
    std::sort(arver[i].begin(), arver[i].end());
    ++num;
}
void PrintVer(std::vector<std::deque<int>> &arver, int i)
{
    printf("%d --------------------------------------------\n", i);
    for (auto &x : arver[i])
    {
        printf("%5d", x);
    }
    printf("\n-------------------------------------------------\n");
}


int main()
{
    std::vector<std::deque<int> > arver;
    arver.resize(n,std::deque<int>(m));
    for(int i= 0;i<n;++i)
    {
      //  arver[i].resize(m,0);
    }
    std::chrono::_V2::system_clock::time_point startTime;
    std::chrono::_V2::system_clock::time_point endTime;
    std::chrono::milliseconds diff;
    {
        tulun::CachedThreadPool mypool;

        startTime = std::chrono::high_resolution_clock().now();
        for (int i = 0; i < n; ++i)
        {
           
            RandValue(arver, i, m);
            mypool.AddTask(std::bind(RandValue, std::ref(arver), i, m));
        } 
        lat.wait();
        endTime = std::chrono::high_resolution_clock().now();
        diff = std::chrono::duration_cast<std::chrono::milliseconds>(endTime - startTime);
        cout << "Rand Init: " << diff.count() << endl;
        cout << mypool.getThreadNum() << endl;

       
        startTime = std::chrono::high_resolution_clock().now();
        for (int i = 0; i < n; ++i)
        {
            SortVer(arver,i);
            mypool.AddTask(std::bind(SortVer, std::ref(arver), i)); //??
        }
    }
    endTime = std::chrono::high_resolution_clock().now();
    diff = std::chrono::duration_cast<std::chrono::milliseconds>(endTime - startTime);
    cout << "Sort: " << diff.count() << endl;
    cout << "num: " << num.load() << endl;
    for (int i = 0; i < n; ++i)
    {
        PrintVer(arver,i);
    }

    return 0;
}


const int n = 1000;
my_latch lat(4000);
void SortVec()
{
    std::vector<int> vec;
    for(int i = 0;i < n;++i)
    {
        vec.push_back(rand()% 1000);
    }
    std::sort(vec.begin(),vec.end());
    lat.count_down();
}
int main()
{
    tulun::CachedThreadPool threadpool;
    int m = 1000;
    for(int i =0;i<m;++i)
    {
        threadpool.AddTask(SortVec);
    }
    lat.wait();
    return 0;
}
void Add(int a, int b)
{
    int c = a + b;
    printf("c=%d \n", c);
}
int main()
{
    tulun::FiexdThreadPool threadpool(4);

}

int Add(int a, int b)
{
    return a + b;
}
int main()
{
    tulun::FiexdThreadPool threadpool(4);
    auto it = threadpool.Submit(Add, 23, 34);
    cout<<it.get()<<endl;
    return 0;
}

int main()
{
    tulun::FiexdThreadPool threadpool(4);
    threadpool.AddTask(std::bind(Add, 12, 23));
    auto it = threadpool.Submit(12, 23);
    cout<<it.get()<<endl;
}

const int n = 1000;
my_latch lat(2000);
void VecSort()
{
    std::vector<int> vec;
    for (int i = 0; i < n; ++i)
    {
        vec.push_back(rand() % 1000);
    }
    sort(vec.begin(), vec.end());
    lat.count_down();
}
int main()
{
    tulun::FiexdThreadPool threadpool(2);
    int m = 2000;
    for (int i = 0; i < m; ++i)
    {
        threadpool.AddTask(VecSort);
    }
    lat.wait();
    return 0;
}

my_latch tag(3);
void funa(void)
{
    cout << "func" << endl;
    tag.count_down();
}
void funb(int x)
{
    cout << "funb: x" << x << endl;
    tag.count_down();
}
class Bar
{
    int value;

public:
    Bar(int x = 0) : value(x) {}
    void func(int x)
    {
        cout << "bar::func: x " << x << " value: " << value << endl;
        tag.count_down();
    }
};
int main()
{
    tulun::FiexdThreadPool threadpool(2);
    Bar bar(10);
    threadpool.AddTask(funa);
    threadpool.AddTask(std::bind(funb, 20));

    threadpool.AddTask(std::bind(&Bar::func, &bar, 30));

    // std::this_thread::sleep_for(std::chrono::seconds(5));
    tag.wait();
    return 0;
}


tulun::FiexdThreadPool pool;
void my_malloc(int size, std::promise<int *> &c_promise)
{
    int *p = (int *)malloc(size);
    int a = 10;
    c_promise.set_value(p);
}
void my_free(int *p)
{
    free(p);
}
void my_a()
{
    int n = 10;
    std::promise<int *> c_promise;
    std::future<int *> a_future = c_promise.get_future();
    std::function<void(void)> f = std::bind(my_malloc, sizeof(int) * n, std::ref(c_promise));
    pool.AddTask(f);
    int *p = a_future.get();
    if (p == nullptr)
    {
        cout << "失败..." << endl;
        exit(1);
    }
    *p = 5;
    cout << "p: " << p << " *p: " << *p << endl;
    pool.AddTask(std::bind(my_free, p));
}
void my_b()
{
    int n = 5;
    std::promise<int *> c_promise;
    std::future<int *> a_future = c_promise.get_future();
    std::function<void(void)> f = std::bind(my_malloc, sizeof(int) * n, std::ref(c_promise));
    pool.AddTask(f);
    int *p = a_future.get();
    if (p == nullptr)
    {
        cout << "失败..." << endl;
        exit(1);
    }
    *p = 10;
    cout << "p: " << p << " *p: " << *p << endl;
    pool.AddTask(std::bind(my_free, p));
}
void my_c()
{
    int n = 1;
    std::promise<int *> c_promise;
    std::future<int *> a_future = c_promise.get_future();
    std::function<void(void)> f = std::bind(my_malloc, sizeof(int) * n, std::ref(c_promise));
    pool.AddTask(f);
    int *p = a_future.get();
    if (p == nullptr)
    {
        cout << "失败..." << endl;
        exit(1);
    }
    *p = 15;
    cout << "p: " << p << " *p: " << *p << endl;
    pool.AddTask(std::bind(my_free, p));
}
int main()
{
    std::thread tha(my_a);
    std::thread thb(my_b);
    std::thread thc(my_c);
    tha.join();
    thb.join();
    thc.join();
    return 0;
}


tulun::FiexdThreadPool pool;
void Add(int a, int b, std::promise<int> &c_promise)
{
    cout << "add begin..." << endl;
    std::this_thread::sleep_for(std::chrono::milliseconds(2000));
    int c = a + b;
    c_promise.set_value(c);
    std::this_thread::sleep_for(std::chrono::milliseconds(1000));
    cout << "add end..." << endl;
}
void add_a()
{
    std::promise<int> c_promise;
    std::future<int> a_fature = c_promise.get_future();
    std::function<void(void)> f = std::bind(Add, 10, 20, std::ref(c_promise));
    pool.AddTask(f);
    cout << "add_a:" << a_fature.get() << endl;
}
void add_b()
{
    std::promise<int> c_promise;
    std::future<int> a_fature = c_promise.get_future();
    std::function<void(void)> f = std::bind(Add, 20, 30, std::ref(c_promise));
    pool.AddTask(f);
    cout << "add_b:" << a_fature.get() << endl;
}
void add_c()
{
    std::promise<int> c_promise;
    std::future<int> a_fature = c_promise.get_future();
    std::function<void(void)> f = std::bind(Add, 30, 40, std::ref(c_promise));
    pool.AddTask(f);
    cout << "add_a:" << a_fature.get() << endl;
}
int main()
{
    std::thread tha(add_a);
    std::thread thb(add_b);
    std::thread thc(add_c);
    tha.join();
    thb.join();
    thc.join();
    return 0;
}

#endif